/*******************************************************************************
 * @file Dining.cpp
 *
 * Main entry point for the dining philosophs application.
 * For building an executeable the boost-libraries for date-time and thread have to 
 * be either linked statically (default) into the application or
 * linked dynamically. In the second case you have to use BOOST_ALL_DYN_LINK as a preprocessor
 * statement when building. You also have to copy the appropriate .dll files into the same folder as the 
 * executeable when linking dynamically.
 * 
 * @package Dining.
 * 
 * @author mk
 * @date 03/01/2008 13:50:21
 * @version 0.1
 ******************************************************************************/

#include "Table.h"
#include "Assert.h"
#include "Logging.h"
#include "Globals.h"

#include <boost/smart_ptr.hpp>

#undef TRACE_FUNC
#define TRACE_FUNC(x)

int main()
{
	TRACE_FUNC("main");

#if 0
	{
		using namespace Logging;
		LogFilter filter;
		filter.push_back("INFO");
		filter.push_back("DEBUG");
		filter.push_back("EVENT");
		filter.push_back("ERROR");
		filter.push_back("WARNING");
		filter.push_back("TRACE");

		CFilteredLogger logger("./output.log", filter);

		logger.Get("INFO") << "information" << std::endl;
		logger.Get("EVENT") << "event" << std::endl;
		logger.Get("ERROR") << "error" << std::endl;
		logger.Get("WARNING") << "warning" << std::endl;
		logger.Get("DEBUG") << "debug" << std::endl;
		logger.Get("TRACE") << "trace" << std::endl;

		FilteredLogger::Setup("./output.log", filter);

		LOG_DBG("debug message");
		LOG_INFO("info message");
		LOG_WARNING("warning message");
		LOG_ERROR("error message");

		FilteredLogger::Close();
	}
#else
	/** @brief Class for encapsulation of the log lifetime manager. */
	class LogLifeTime
	{
	public:
		LogLifeTime()
		{
			Logging::LogFilter filter;
			filter.push_back("INFO");
			filter.push_back("DEBUG");
			filter.push_back("EVENT");
			filter.push_back("ERROR");
			filter.push_back("WARNING");
			filter.push_back("TRACE");
			Logging::FilteredLogger::Setup("./output.log", filter);
		}
		~LogLifeTime()
		{
			Logging::FilteredLogger::Close();
		}
	} life;

	{
		using namespace std;
		using namespace Dining;

		/** Some constants. */
		enum { KPhilosophs = 5 };
		enum { KPortions = 30 };

		/** Base level exception try-catch-block. */
		try
		{
			/** Create a table with a specified amount of philosophs and portions. */
			boost::scoped_ptr<CTable> t(new CTable(KPhilosophs, KPortions));
		    
			/** Start() returns when all philosophs have finshed (all portions have been consumed). */
			t->Start();
		}
		catch (exception& e)
		{
			LOG_ERROR(e.what());
			cerr << "Error: " << e.what() << "\n";
			return -1;
		}
		catch (...)
		{
			LOG_ERROR("Exception of unknown type!");
			cerr << "Exception of unknown type!\n";
			return -2;
		}
	}
#endif

	return 0;
}
